/*
事件分发器
每一个线程只能有一个eventloop对象
*/

#pragma once
#include<functional>
#include<memory>
#include <mutex>
#include <vector>
#include "channel.h"
#include "epoll.h"

class Epoll;
class EventLoop{
public:
    using Functor=std::function<void()>;
    EventLoop();
    ~EventLoop();
    //reactor启动
    void loop();
    //停止eventloop
    void quit();
    //关闭某个socket
    void shutdown(std::shared_ptr<Channel> ev);

    //m_wakefd被唤醒时调用
    void handleRead();
    void handleConn();
    //保证每一个线程只有一个eventloop对象
    bool isInLoopThread();
    
    void remove_event(std::shared_ptr<Channel> ev);
    void add_event(std::shared_ptr<Channel> ev, int timeout = 0);
    void update_event(shared_ptr<Channel> ev,int timerout = 0);

    //保证读写是在eventloopThread里进行的
    void queueInloop(Functor&& cb);
    //处理m_pendingFunctors
    void dePendingFunctors();
private:
    void wakeup();
private:
    bool m_isLoop;
    std::shared_ptr<Epoll> m_poller;
    std::mutex m_mtx;
    bool m_quit;    //注意和m_isLoop区别
    //eventloop是监听epollfd的, 而m_pendingFunctors里的函数的执行也是在eventloop里唤起的,如果epollfd迟迟没有事件发生, m_pendingFunctors就会得不到及时处理, 所以这里用一个wakeupfd的可读事件触发eventloop
    int m_wakefd;
    //管理eventfd
    std::shared_ptr<Channel> m_channel;
    //要调用的函数,相当于一个阻塞队列
    std::vector<Functor> m_pendingFunctors;
    //当前线程ID
    const pid_t m_threadID;
};
